我們這邊將改寫原本 本系列第10篇中使用的 <bounds/>
https://github.com/pmndrs/drei#bounds
function Foo() {
const bounds = useBounds()
useEffect(() => {
// Calculate scene bounds
bounds.refresh().clip().fit()
// Or, focus a specific object or box3
// bounds.refresh(ref.current).clip().fit()
// bounds.refresh(new THREE.Box3()).clip().fit()
<Bounds>
<Foo />
建立另外兩個目標物後
import * as THREE from 'three'
import React, { useRef, Suspense, useState } from 'react'
import { Canvas, useFrame, useThree } from '@react-three/fiber'
import { OrbitControls, Bounds, useBounds, BakeShadows, Environment, ContactShadows, Cloud, Sky } from '@react-three/drei'
import { Room } from './Room'
import ModelDraco from './ModelDracoOG'
import GoldenText from './GoldenText'
import ModelCupboard from './Model/ModelCupboard'
import ModelWall from './Model/ModelWall'
import ModelCMD from './ModelCMD'
import { OmitProps } from 'antd/lib/transfer/ListBody'
function Rig() {
const camera = useThree((state) => state.camera)
const vec = new THREE.Vector3()
return useFrame((state) => {
// camera.position.x = Math.sin(state.clock.elapsedTime) * 20
// camera.position.z = Math.sin(state.clock.elapsedTime) * 20
// camera.position.z = state.clock.elapsedTime * 10
// const ref = useRef()
// useFrame(() => {
// camera.position(vec.set(10, 2000, 10), 0.05)
// camera.position.lerp(vec.set(10, 2000, 10), 0.05)
// camera.position.lerp(vec.set(10, 1050, 10), vec.set(10, 50, 10), 0.05)
// ref.current.position.lerp(vec.set(mouse.x * 1, mouse.y * 0.1, 0), 0.1)
// ref.current.rotation.y = THREE.MathUtils.lerp(ref.current.rotation.y, (-mouse.x * Math.PI) / 20, 0.1)
// })
camera.position
})
}
export default function App({ ready }) {
const [clicked_to_Left, click_to_Left] = useState(false)
const [clicked_to_Right, click_to_Right] = useState(false)
const ref_zero = useRef()
const ref_Left = useRef()
return (
<Canvas orthographic shadows dpr={[1, 2]} camera={{ position: [10, 10, 10], zoom: 10 }}>
<Rig />
<Sky azimuth={0.1} turbidity={10} rayleigh={0.5} inclination={0.6} distance={1000} />
{/* <color attach="background" args={['#252530']} /> */}
{/* <color attach="background" args={['#252530']} /> */}
<color attach="background" args={['#FCF4EE']} />
{/* <color attach="background" args={['#E34234']} /> */}
<Environment preset="city" />
<Suspense fallback={null}>
<group scale={5} position={[5, 100, 0]}>
<Cloud position={[-4, -2, -25]} speed={0.2} opacity={1} />
<Cloud position={[4, 2, -15]} speed={0.2} opacity={0.5} />
<Cloud position={[-4, 2, -10]} speed={0.2} opacity={1} />
<Cloud position={[4, -2, -5]} speed={0.2} opacity={0.5} />
<Cloud position={[4, 2, 0]} speed={0.2} opacity={0.75} />
</group>
<group position={[0, 10, 0]}>
<Cloud position={[-4, -2, -25]} speed={0.2} opacity={1} />
<Cloud position={[4, 2, -15]} speed={0.2} opacity={0.5} />
<Cloud position={[-4, 2, -10]} speed={0.2} opacity={1} />
<Cloud position={[4, -2, -5]} speed={0.2} opacity={0.5} />
<Cloud position={[4, 2, 0]} speed={0.2} opacity={0.75} />
</group>
<group position={[10, 10, 0]}>
<Cloud position={[-4, -2, -25]} speed={0.2} opacity={1} />
<Cloud position={[4, 2, -15]} speed={0.2} opacity={0.5} />
<Cloud position={[-4, 2, -10]} speed={0.2} opacity={1} />
<Cloud position={[4, -2, -5]} speed={0.2} opacity={0.5} />
<Cloud position={[4, 2, 0]} speed={0.2} opacity={0.75} />
</group>
<group position={[-10, 10, 5]}>
<Cloud position={[-4, -2, -25]} speed={0.2} opacity={1} />
<Cloud position={[4, 2, -15]} speed={0.2} opacity={0.5} />
<Cloud position={[-4, 2, -10]} speed={0.2} opacity={1} />
<Cloud position={[4, -2, -5]} speed={0.2} opacity={0.5} />
<Cloud position={[4, 2, 0]} speed={0.2} opacity={0.75} />
</group>
</Suspense>
<ambientLight intensity={0.01} />
{/* <hemisphereLight intensity={0.125} color="#734036" groundColor="red" /> */}
{/* <hemisphereLight intensity={0.125} color="#8040df" groundColor="red" /> */}
{/* <spotLight castShadow color="orange" intensity={2} position={[-50, 50, 40]} angle={0.25} penumbra={1} shadow-mapSize={[128, 128]} shadow-bias={0.00005} /> */}
<group scale={10}>
{/* <spotLight
castShadow
color="orange"
intensity={1}
position={[50, 100, 0]}
angle={0.15}
penumbra={0.5}
shadow-mapSize={[64, 64]}
shadow-bias={-0.000001}
target-position={[0, 20, 0]}
/> */}
</group>
<Suspense fallback={null}>
{/* <Bounds fit clip observe margin={1}> */}
<group position={[0, 0, 0]}>
{/* <group position={[5, 43, -12]}> */}
<group scale={10}>
{/* <spotLight
castShadow
color="orange"
intensity={1}
position={[50, 100, 0]}
angle={0.15}
penumbra={0.5}
shadow-mapSize={[64, 64]}
shadow-bias={-0.000001}
target-position={[0, 20, 0]}
/> */}
</group>
<group scale={1.7} position={[4 - 5, 20 - 5, -7]}>
<ModelWall scale={1} position={[-8.8 * 3.5, 0, 8.8 * 2.5]} rotation={[Math.PI / 2, 0, Math.PI / 2]} receiveShadow />
<ModelWall scale={1} position={[-8.8 * 3.5, 0, 8.8 * 1.5]} rotation={[Math.PI / 2, 0, Math.PI / 2]} receiveShadow />
<ModelWall scale={1} position={[-8.8 * 3.5, 0, 8.8 * 0.5]} rotation={[Math.PI / 2, 0, Math.PI / 2]} receiveShadow />
<ModelWall scale={1} position={[-8.8 * 3, 0, 0]} rotation={[Math.PI / 2, 0, 0]} receiveShadow />
<ModelWall scale={1} position={[-8.8 * 2, 0, 0]} rotation={[Math.PI / 2, 0, 0]} receiveShadow />
<ModelWall scale={1} position={[-8.8, 0, 0]} rotation={[Math.PI / 2, 0, 0]} receiveShadow />
<ModelWall scale={1} position={[0, 0, 0]} rotation={[Math.PI / 2, 0, 0]} receiveShadow />
<ModelWall scale={1} position={[8.8, 0, 0]} rotation={[Math.PI / 2, 0, 0]} receiveShadow />
<ModelWall scale={1} position={[8.8 * 2, 0, 0]} rotation={[Math.PI / 2, 0, 0]} receiveShadow />
<ModelWall scale={1} position={[8.8 * 3, 0, 0]} rotation={[Math.PI / 2, 0, 0]} receiveShadow />
<ModelWall scale={1} position={[8.8 * 3.5, 0, 8.8 * 2.5]} rotation={[Math.PI / 2, 0, Math.PI / 2]} receiveShadow />
<ModelWall scale={1} position={[8.8 * 3.5, 0, 8.8 * 1.5]} rotation={[Math.PI / 2, 0, Math.PI / 2]} receiveShadow />
<ModelWall scale={1} position={[8.8 * 3.5, 0, 8.8 * 0.5]} rotation={[Math.PI / 2, 0, Math.PI / 2]} receiveShadow />
</group>
<group scale={1.5} position={[-2 - 5, 13.5, -3]}>
{/* <ModelCupboard position={[-5, 0, 0]} receiveShadow /> */}
<ModelCupboard scale={[-1, 1, 1]} position={[-26.5 + 2, 0, 0]} />
<ModelCupboard scale={[-1, 1, 1]} position={[-14.5 + 2, 0, 0]} />
<ModelCupboard position={[22.5 - 2, 0, 0]} />
<ModelCupboard scale={[-1, 1, 1]} position={[34.5 - 2, 0, 0]} />
</group>
{/* <group scale={1.5} position={[-2 - 5, 13.5, -3]}>
<ModelCupboard position={[-5, 0, 0]} receiveShadow />
<ModelCupboard scale={[-1, 1, 1]} position={[7.1, 0, 0]} receiveShadow />
<ModelCupboard position={[19.2, 0, 0]} receiveShadow />
</group> */}
<spotLight position={[5, 30, 30]} angle={0.5} penumbra={1} />
<Bounds fit clip observe margin={1}>
<SelectToZoom clicked_to_Left={clicked_to_Left} click_to_Left={click_to_Left} click_to_Right={click_to_Right} clicked_to_Right={clicked_to_Right}>
<group dispose={null}>
<ModelCMD
onClick={(event) => click_to_Left(!clicked_to_Left)}
position={[0, 21, 0]}
scale={3}
rotation={[-Math.PI / 2 + 0.5, -Math.PI / 2, 0]}
/>
<ModelDraco scale={10} position={[5 - 6, 1.5 + 1, 1]} receiveShadow castShadow />
<group position={[5 - 5, 43 + 2, -11]}>
<GoldenText scale={5} rotation={[0, Math.PI / 2, Math.PI / 2 + 0.1]} receiveShadow />
</group>
</group>
<group>
{/* <ModelCMD
onClick={(event) => click_to_Left(!clicked_to_Left)}
position={[-40, 21, 20]}
scale={3}
rotation={[-Math.PI / 2 + 0.5, -Math.PI / 2, 0]}
/> */}
</group>
</SelectToZoom>
</Bounds>
<ContactShadows position={[0, 0, 0]} scale={[100, 40]} blur={10} far={20} receiveShadow castShadow />
{/* <ModelDraco scale={10} position={[5 - 5, 1.5 + 1, 5.5 * 2]} receiveShadow /> */}
</group>
{/* </Bounds> */}
</Suspense>
<mesh scale={8.8 * (9 + 3)} rotation={[-Math.PI / 2, 0, 0]} position={[0, 0, 20]} castShadow receiveShadow>
<planeGeometry />
{/* <meshDepthMaterial color={'red'} /> */}
<meshBasicMaterial receiveShadow attach="material" color="#994639" opacity={0.9} />
{/* <meshLambertMaterial receiveShadow attach="material" color="#CB1B45" opacity={0.9} /> */}
{/* <meshBasicMaterial attach="material" color="#64363C" opacity={0.9} /> */}
</mesh>
{/* <Bounds fit clip observe margin={1}> */}
{/* <Room position={[0, 0, 15]} scale={[0.1, 0.19, 0.1]} /> */}
{/* </Bounds> */}
<BakeShadows />
<OrbitControls
ref={ref_zero}
// position={clicked_to_Left ? [100, 10, 10] : [10, 10, 10]}
makeDefault
//clicked_to_Right, click_to_Right
// minAzimuthAngle={clicked_to_Left ? -Math.PI / 16 + Math.PI / 2 : -Math.PI / 16}
// maxAzimuthAngle={clicked_to_Left ? Math.PI / 16 + Math.PI / 2 : Math.PI / 16}
minAzimuthAngle={clicked_to_Left && clicked_to_Right ? (clicked_to_Left ? -Math.PI / 16 + Math.PI / 2 : -Math.PI / 16 + -Math.PI / 2) : -Math.PI / 16}
maxAzimuthAngle={clicked_to_Left && clicked_to_Right ? (clicked_to_Left ? Math.PI / 16 + Math.PI / 2 : Math.PI / 16 - Math.PI / 2) : Math.PI / 16}
// maxAzimuthAngle={Math.PI / 6}
minPolarAngle={Math.PI / 3}
maxPolarAngle={Math.PI / 3}
enableZoom={true}
enablePan={true}
zoomSpeed={0.3}
// target={ref_zero}
/>
{/* <OrbitControls
makeDefault
minAzimuthAngle={0}
maxAzimuthAngle={Math.PI / 2}
minPolarAngle={Math.PI / 3}
maxPolarAngle={Math.PI / 3}
enableZoom={true}
enablePan={true}
zoomSpeed={0.3}
/> */}
{/* <gridHelper args={[1000, 200, '#151515', '#020202']} position={[0, -4, 0]} /> */}
{/* <mesh scale={200} rotation={[-Math.PI / 2, 0, 0]} position={[0, -4, 0]} receiveShadow>
<planeGeometry />
<shadowMaterial transparent opacity={0.3} />
</mesh> */}
</Canvas>
)
}
// This component wraps children in a group with a click handler
// Clicking any object will refresh and fit bounds
function SelectToZoom({ children, ...Props }) {
const api = useBounds()
const ref = useRef()
const [toLeft, setToLef] = useState(false)
return (
<group
ref={ref}
// onClick={(e) => (e.stopPropagation(), e.delta <= 2 && api.refresh(e.object).fit())}
onClick={(e) => {
e.stopPropagation()
// console.log(e.delta)
// console.log(ref_B.position)
Props.clicked_to_Left ? api.refresh(ref.current.children[4]).fit() : api.refresh(ref.current.children[3]).fit()
// e.delta <= 2 && api.refresh(ref.current.children[1].children[0]).fit()
// console.log(e.object)
// console.log(ref)
// console.log(ref.current.children[1].children[0])
}}
onPointerMissed={(e) => e.button === 0 && api.refresh().fit()}>
{children}
<ModelCMD
name="ModelCMD_A"
onClick={(event) => {
setToLef(!toLeft)
Props.click_to_Left(false)
Props.click_to_Right(false)
}}
position={[0, 22, 0]}
scale={4}
rotation={[-Math.PI / 2 + 0.5, -Math.PI / 2, 0]}
/>
<group
name="ModelCMD_B"
onClick={(event) => {
setToLef(!toLeft)
Props.click_to_Left(!Props.clicked_to_Left)
}}
scale={1.5}
position={[-50, 13.5, 6]}
rotation={[0, Math.PI / 2, 0]}>
{/* <ModelCupboard position={[-5, 0, 0]} receiveShadow /> */}
<ModelCupboard scale={[-1, 1, 1]} position={[-16.5, 0, 0]} />
<ModelCupboard scale={[-1, 1, 1]} position={[-4.5, 0, 0]} />
</group>
<group
name="ModelCMD_C"
onClick={(event) => {
setToLef(!toLeft)
Props.click_to_Right(!Props.clicked_to_Right)
}}
scale={1.5}
position={[50, 13.5, 40]}
rotation={[0, -Math.PI / 2, 0]}>
<ModelCupboard scale={[-1, 1, 1]} position={[-16.5, 0, 0]} />
<ModelCupboard scale={[-1, 1, 1]} position={[-4.5, 0, 0]} />
</group>
{/* <ModelCMD
name="ModelCMD_B"
ref={ref_B}
onClick={(event) => {
setToLef(!toLeft)
Props.click_to_Left(!Props.clicked_to_Left)
}}
position={[-40, 21, 20]}
scale={4}
rotation={[-Math.PI / 2 + 0.5, -Math.PI / 2, 0]}
/> */}
</group>
)
}